﻿using System;
using System.Windows.Forms;
using System.Drawing;
using Qurihara;
using System.Collections;
using System.Xml;
using Qurihara.Anm;
//using System.IO;
using System.Threading;
using System.Net;
using Qurihara.QBasic;
using System.Text;
using System.Collections.Generic;
using System.Deployment.Application;

using Qurihara.localhost;

namespace Qurihara.OSCCom
{
    public class WebComCore :IComCore
    {
        public static bool AntiProxy = false;
        public static string DefaultGroupName = "default";
        public static int UpdateInterval = 2000;
        public static int SendInterval = 500;

        private static WebService ws;

        protected static System.Windows.Forms.Timer timer;
        protected static System.Windows.Forms.Timer sendTimer;
        //private static Mutex mutInvalidated = new Mutex();

        protected static Queue sendQueue;
        protected static List<localhost.KMessage> sendList;

        protected static DateTime lastUpdate;

        //protected static List<WebComCore> listeners;
        protected static ArrayList listeners;
        private static bool initialized = false;

        private static bool connected = false;

        protected string groupName;
        public string GroupName
        {
            get { return groupName; }
            set { groupName = value; }
        }

        static WebComCore()
        {
            ResetUpdates();           

            sendQueue = new Queue();
            sendQueue = Queue.Synchronized(sendQueue);
            sendList = new List<KMessage>();

            listeners = new ArrayList();
            listeners = ArrayList.Synchronized(listeners);

            AntiProxy = Qurihara.QBasic.Util.IsPropertyTrue("WebComCore.AntiProxy");
        }

        public WebComCore()
        {
            //lastUpdate = DateTime.Now;
            //sendQueue = new Queue();
            //sendQueue = Queue.Synchronized(sendQueue);
            //sendList = new List<KMessage>();
            groupName = DefaultGroupName;
        }
        //public WebComCore(string groupname)
        //{
        //    groupName = groupname;
        //}
        #region Configuration

        public virtual void Initialize()
        {
            if (!initialized)
            {
                initialized = true;
                RenewWebService();

                timer = new System.Windows.Forms.Timer();
                timer.Interval = UpdateInterval;
                timer.Tick += new EventHandler(timer_Tick);
                timer.Enabled = true;
                timer.Start();

                sendTimer = new System.Windows.Forms.Timer();
                sendTimer.Interval = SendInterval;
                sendTimer.Tick += new EventHandler(sendTimer_Tick);
                sendTimer.Enabled = true;
                sendTimer.Start();
            }

            listeners.Add(this);
        }

        public virtual void Dispose()
        {
            //timer.Stop();
            //timer.Enabled = false;
            //timer.Dispose();

            listeners.Remove(this);
        }

        #endregion

        private void RenewWebService()
        {
            if (ws != null)
            {
                ws.SendLogCompleted -= new SendLogCompletedEventHandler(ws_SendLogCompleted);
                ws.GetLogUpdateCompleted -= new Qurihara.localhost.GetLogUpdateCompletedEventHandler(ws_GetLogUpdateCompleted);
                ws.Dispose();
                ws = null;
            }
            ws = GetService();
            ws.Timeout = (int)(UpdateInterval * 0.9);
            ws.GetLogUpdateCompleted += new Qurihara.localhost.GetLogUpdateCompletedEventHandler(ws_GetLogUpdateCompleted);
            ws.SendLogCompleted += new SendLogCompletedEventHandler(ws_SendLogCompleted);
        }

        #region WebService
        private WebService GetService()
        {
            WebService kw = new WebService();
            string p = "";
            if (ApplicationDeployment.IsNetworkDeployed)
            {
                string site = ApplicationDeployment.CurrentDeployment.ActivationUri.Host;
                kw.Url = kw.Url.Replace("//localhost/"
                    , "//" + site + "/");
            }
            else
                if (Util.GetStringProperty("OSCCom.ServerUrl", ref p))
                {
                    string site = p;
                    kw.Url = kw.Url.Replace("//localhost/"
                        , "//" + site + "/");
                }

            //if (AntiProxy)
            //{
            //    kw.Url = AnonimizeAsmx(kw.Url);
            //}

            return kw;
        }
        // うまくうごかなかった。
        private string AnonimizeAsmx(string src)
        {
            src = src.Replace(".asmx", "_" + DateTime.Now.Ticks.ToString().Substring(0,14) + "_.html");
            return src;
        }
        #endregion

        public static void ResetUpdates()
        {
            //lastUpdate = DateTime.Now;
            lastUpdate = new DateTime(2008, 1, 1); // 最初は過去すべてのデータを持ってくる。
        }

        public virtual void Send(string senderName, string destName, string adr, string val)
        {
            localhost.KMessage ms = new Qurihara.localhost.KMessage();
            ms.Group = groupName;// "default";
            //ms.SenderName = name;
            ms.SenderName = senderName;
            ms.DestName = destName;
            ms.Log = adr +" "+ val;
            sendQueue.Enqueue(ms);
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            //受信タイミングならば受信する
            if (AntiProxy) RenewWebService();
            ws.GetLogUpdateAsync(lastUpdate,groupName);// "default");//,name);
        }

        void sendTimer_Tick(object sender, EventArgs e)
        {
            //送信キューがたまっていたらまとめて送信する
            if (sendQueue.Count > 0)
            {
                sendList.Clear();
                while (sendQueue.Count > 0)
                {
                    localhost.KMessage ms = (localhost.KMessage)sendQueue.Dequeue();
                    sendList.Add(ms);
                }
                localhost.KMessage[] msgs = sendList.ToArray();// (localhost.KMessage[])sendList.ToArray();
                try
                {
                    if (AntiProxy) RenewWebService();
                    //ws.SendLog(msgs);
                    //ws.SendLogAsync(msgs);
                    ws.SendLogAsync(msgs,msgs);
                }
                catch
                {
                }
            }
        }

        void ws_SendLogCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
        {
            if (e.Cancelled || e.Error != null)
            {
                //MessageBox.Show("sending error");
                localhost.KMessage[] msgs = (localhost.KMessage[])e.UserState;
                foreach (KMessage msg in msgs) sendQueue.Enqueue(msg);
            }
        }


        void ws_GetLogUpdateCompleted(object sender, Qurihara.localhost.GetLogUpdateCompletedEventArgs e)
        {
            if (!e.Cancelled && e.Error == null)
            {
                connected = true;
                //受信したものがあればパースを呼び出す。
                //mutInvalidated.WaitOne();
                DateTime tTime = lastUpdate;
                foreach (localhost.KMessage ms in e.Result)
                {
                    if (ms.Time > lastUpdate)
                    {
                        tTime = ms.Time;
                        //if (!ms.SenderName.Equals(name))
                        //{
                        string[] com = ms.Log.Split(' ');
                        foreach (WebComCore core in listeners)
                        {
                            MessageEventArgs me = new MessageEventArgs(ms.Time, ms.SenderName, ms.DestName, com[0], com[1]);
                            core.FireMessageReceived(me);
                        }
                        //if (MessageReceived != null) MessageReceived(this, new MessageEventArgs(ms.SenderName,ms.DestName, com[0], com[1]));
                        //}
                    }
                }
                lastUpdate = tTime;
                //mutInvalidated.ReleaseMutex();
            }
            else
            {
                connected = false;
            }
        }

        protected void FireMessageReceived(MessageEventArgs e)
        {
            if (MessageReceived != null) MessageReceived(this, e);
        }

        #region IComCore implements

        protected string name = "default_name";
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        protected string ip = "localhost";
        public string Ip
        {
            get { return ip; }
        }
        protected int mPort = 5501;
        public int MPort
        {
            get { return mPort; }
        }

        public event MessageEventHandler MessageReceived;
        public void ConnectTransmitter(string serverIP, int serverPort)
        {
        }

        public bool IsConnected
        {
            get { return connected;}
        }
        #endregion
    }
}
